# -*- coding: utf-8 -*-
import frappe
from frappe.model.document import Document

class ScrapTransaction(Document):
    """
    余料事务记录控制器
    用于记录余料的所有数量变化事务
    """
    
    def validate(self):
        """验证事务记录数据"""
        self.validate_scrap_material()
        self.validate_quantity_change()
        self.validate_transaction_type()
        self.set_material_details()
    
    def validate_scrap_material(self):
        """验证余料是否存在"""
        if self.scrap_material and not frappe.db.exists("Scrap Material", self.scrap_material):
            frappe.throw(f"余料 {self.scrap_material} 不存在")
    
    def validate_quantity_change(self):
        """验证数量变化"""
        if self.quantity_change == 0:
            frappe.throw("数量变化不能为零")
        
        if self.old_quantity < 0 or self.new_quantity < 0:
            frappe.throw("数量不能为负数")
        
        # 验证数量变化是否一致
        expected_new_quantity = self.old_quantity + self.quantity_change
        if abs(self.new_quantity - expected_new_quantity) > 0.0001:
            frappe.throw(f"数量变化不一致，期望新数量为 {expected_new_quantity}，实际为 {self.new_quantity}")
    
    def validate_transaction_type(self):
        """验证事务类型和数量变化方向是否一致"""
        if self.transaction_type == "入库" and self.quantity_change <= 0:
            frappe.throw("入库事务的数量变化必须为正数")
        elif self.transaction_type in ["出库", "领料", "消耗"] and self.quantity_change >= 0:
            frappe.throw(f"{self.transaction_type}事务的数量变化必须为负数")
    
    def set_material_details(self):
        """设置余料详细信息"""
        if self.scrap_material:
            material = frappe.get_doc("Scrap Material", self.scrap_material)
            self.material_type = material.material_type
            self.material_name = material.material_name
            self.color = material.color
            self.length = material.length
            self.width = material.width
            self.thickness = material.thickness
            self.unit = material.unit
            self.unit_price = material.unit_price
            self.warehouse = material.warehouse
            self.location = material.location
    
    def before_save(self):
        """保存前处理"""
        # 设置参考文档类型和名称
        if self.reference_document:
            doc = frappe.get_doc(self.reference_document)
            self.reference_doctype = doc.doctype
            self.reference_name = doc.name
    
    def on_update(self):
        """更新后处理"""
        # 更新余料的最后事务日期
        if self.scrap_material:
            frappe.db.set_value("Scrap Material", self.scrap_material, "last_transaction_date", self.transaction_date)
    
    @staticmethod
    def create_transaction(scrap_material, transaction_type, quantity_change, 
                          old_quantity, new_quantity, reference_doc=None, remarks=None):
        """
        创建余料事务记录
        
        Args:
            scrap_material (str): 余料ID
            transaction_type (str): 事务类型
            quantity_change (float): 数量变化
            old_quantity (float): 旧数量
            new_quantity (float): 新数量
            reference_doc (str): 参考文档
            remarks (str): 备注
            
        Returns:
            str: 事务记录ID
        """
        try:
            transaction = frappe.get_doc({
                "doctype": "Scrap Transaction",
                "scrap_material": scrap_material,
                "transaction_type": transaction_type,
                "transaction_date": frappe.utils.nowdate(),
                "transaction_time": frappe.utils.nowtime(),
                "quantity_change": quantity_change,
                "old_quantity": old_quantity,
                "new_quantity": new_quantity,
                "reference_document": reference_doc,
                "remarks": remarks,
                "created_by": frappe.session.user
            })
            
            transaction.insert(ignore_permissions=True)
            return transaction.name
        except Exception as e:
            frappe.log_error(f"创建余料事务记录失败: {str(e)}", "余料管理系统")
            frappe.throw(f"创建余料事务记录失败: {str(e)}")
    
    @staticmethod
    def get_transaction_history(scrap_material, limit=20):
        """
        获取余料的事务历史
        
        Args:
            scrap_material (str): 余料ID
            limit (int): 返回记录数限制
            
        Returns:
            list: 事务记录列表
        """
        return frappe.db.get_all("Scrap Transaction",
            filters={"scrap_material": scrap_material},
            fields=["name", "transaction_type", "transaction_date", "transaction_time", 
                   "quantity_change", "old_quantity", "new_quantity", 
                   "reference_doctype", "reference_name", "created_by", "remarks"],
            order_by="transaction_date DESC, transaction_time DESC",
            limit=limit
        )
    
    @staticmethod
    def get_daily_summary(date=None, warehouse=None):
        """
        获取每日事务汇总
        
        Args:
            date (str): 日期，默认为今天
            warehouse (str): 仓库ID
            
        Returns:
            dict: 每日事务汇总
        """
        if not date:
            date = frappe.utils.nowdate()
        
        filters = {"transaction_date": date}
        
        if warehouse:
            filters["warehouse"] = warehouse
        
        # 获取各类型事务的汇总
        summary = frappe.db.get_all("Scrap Transaction",
            filters=filters,
            fields=[
                "transaction_type",
                "SUM(CASE WHEN quantity_change > 0 THEN quantity_change ELSE 0 END) as total_in",
                "SUM(CASE WHEN quantity_change < 0 THEN ABS(quantity_change) ELSE 0 END) as total_out",
                "COUNT(*) as count"
            ],
            group_by="transaction_type"
        )
        
        # 计算总计
        total_in = sum(item.get("total_in", 0) for item in summary)
        total_out = sum(item.get("total_out", 0) for item in summary)
        total_count = sum(item.get("count", 0) for item in summary)
        
        return {
            "date": date,
            "summary": summary,
            "total_in": total_in,
            "total_out": total_out,
            "net_change": total_in - total_out,
            "total_count": total_count
        }
    
    @staticmethod
    def get_monthly_summary(year=None, month=None, warehouse=None):
        """
        获取每月事务汇总
        
        Args:
            year (int): 年份，默认为当前年份
            month (int): 月份，默认为当前月份
            warehouse (str): 仓库ID
            
        Returns:
            dict: 每月事务汇总
        """
        if not year:
            year = frappe.utils.now_datetime().year
        
        if not month:
            month = frappe.utils.now_datetime().month
        
        # 构建日期范围
        start_date = frappe.utils.getdate(f"{year}-{month:02d}-01")
        end_date = frappe.utils.get_last_day(start_date)
        
        filters = {
            "transaction_date": [">=", start_date],
            "transaction_date": ["<=", end_date]
        }
        
        if warehouse:
            filters["warehouse"] = warehouse
        
        # 获取各类型事务的汇总
        summary = frappe.db.get_all("Scrap Transaction",
            filters=filters,
            fields=[
                "transaction_type",
                "SUM(CASE WHEN quantity_change > 0 THEN quantity_change ELSE 0 END) as total_in",
                "SUM(CASE WHEN quantity_change < 0 THEN ABS(quantity_change) ELSE 0 END) as total_out",
                "COUNT(*) as count"
            ],
            group_by="transaction_type"
        )
        
        # 计算总计
        total_in = sum(item.get("total_in", 0) for item in summary)
        total_out = sum(item.get("total_out", 0) for item in summary)
        total_count = sum(item.get("count", 0) for item in summary)
        
        return {
            "year": year,
            "month": month,
            "summary": summary,
            "total_in": total_in,
            "total_out": total_out,
            "net_change": total_in - total_out,
            "total_count": total_count
        }